package com.cz.video.website.processor;

import cn.hutool.core.collection.CollUtil;
import com.cz.video.common.constant.CacheConstants;
import com.cz.video.common.constant.HistoryConstants;
import com.cz.video.common.utils.LuaFileReader;
import com.cz.video.common.utils.redis.RedisUtils;
import com.cz.video.website.service.WebsiteHistoryService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RQueue;
import org.springframework.stereotype.Component;
import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.TaskContext;
import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
import tech.powerjob.worker.log.OmsLogger;

import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 刷新章节观看进度
 */
@Slf4j
@Component
@AllArgsConstructor
public class RefreshHistoryProcessor implements BasicProcessor {

    private final WebsiteHistoryService historyService;

    @Override
    public ProcessResult process(TaskContext context) throws Exception {
        OmsLogger omsLogger = context.getOmsLogger();

        //更新成功则删除缓存
        try {
//            historyService.refreshAll();
            //抽取要刷新的用户
            extractRefreshUserQueue();
            //分批刷新到数据库
            refreshHistory();
            omsLogger.info("历史记录已成功刷新到数据库中");
        }catch (Exception e){
            omsLogger.error("历史记录刷新失败！",e);
            return new ProcessResult(false, context + ": " +"失败" );
        }

        return new ProcessResult(true, context + ": " +"成功" );
    }

    /**
     * 抽取要刷新历史记录的的用户的id队列
     */
    private void extractRefreshUserQueue() {
        //看看是否在抽取之前刚刚抽取过,就直接跳过了
        if (RedisUtils.getCacheObject(CacheConstants.HISTORY_REFRESH_FLAG) != null) {
            return;
        }
        RLock lock = RedisUtils.getClient().getLock(CacheConstants.HISTORY_REFRESH_LOCK);
        try {
            //尝试获取锁
            boolean tryLock = lock.tryLock(6,5, TimeUnit.SECONDS);
            //获取到锁时,没有获取到就不管了
            if (tryLock){
                log.info("获取历史刷新锁成功");
                //获取到锁之后再看看有没有标志，没有再继续执行
                if (RedisUtils.getCacheObject(CacheConstants.HISTORY_REFRESH_FLAG) == null){
                    //在执行脚本之前就设置flag，防止重复提取要刷新的用户
                    RedisUtils.setCacheObject(CacheConstants.HISTORY_REFRESH_FLAG, true, Duration.ofMinutes(HistoryConstants.REFRESH_TIME_INTERVAL));
                    String luaFile = LuaFileReader.readLuaFile("historyRefresh");
                    RedisUtils.execScript(luaFile, CollUtil.newArrayList(CacheConstants.HISTORY_REFRESH_PREFIX,
                        CacheConstants.CACHE_PREFIX + CacheConstants.HISTORY_REFRESH_QUEUE));
                }
            }
        } catch (InterruptedException e) {
            //解锁
            log.error("抽取要刷新历史记录中出现错误",e);
            throw new RuntimeException(e);
        }finally {
            lock.forceUnlock();
            log.info("已解除历史刷新锁");
        }
    }

    /**
     * 分批次的把用户的历史记录刷新到数据库
     */
    private void refreshHistory() {
        //TODO:cz:进行刷新速率的控制
        String key = CacheConstants.CACHE_PREFIX + CacheConstants.HISTORY_REFRESH_QUEUE;
        RQueue<Object> queue = RedisUtils.getClient().getQueue(key);
        while (true){
            List list = queue.poll(HistoryConstants.REFRESH_BATCH_COUNT);
            //如果没了就退出
            if (CollUtil.isNotEmpty(list)){
                historyService.reflushBatch(list);
            }else break;
        }
    }
}
